/**
 * Copyright (c) 2009 blurredVision
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, 
 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or 
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT 
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT 
 * OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
#include "StdAfx.h"
#include "IDrawPrimitive.h"

#ifdef CORE_DIRECTX
#include "dx/DXDrawPrimitive.h"
#endif

IDrawPrimitive::IDrawPrimitive(void)
{
}

IDrawPrimitive::~IDrawPrimitive(void)
{
}

IDrawPrimitive* IDrawPrimitive::CreateSphere(float rad, unsigned int slices, unsigned int stacks)
{
	IDrawPrimitive* newprim = NULL;
	
#ifdef CORE_DIRECTX
	// Create a sphere as a directx instance
	newprim = new directx::DXDrawPrimitive();
	dynamic_cast<directx::DXDrawPrimitive*>(newprim)->createSphere(rad, slices, stacks);
#endif

	newprim->radius = rad;
	newprim->type = TYPE_SPHERE;

	return newprim;
}

IDrawPrimitive* IDrawPrimitive::CreatePlane(const math::Vector3 &norm, float d, const math::Vector2i &tesselation)
{
	IDrawPrimitive* newprim = NULL;

#ifdef CORE_DIRECTX
	// Create a plane as a directx instance
	newprim = new directx::DXDrawPrimitive();
	dynamic_cast<directx::DXDrawPrimitive*>(newprim)->createPlane(norm, d, tesselation);
#endif

	newprim->normal = norm;
	newprim->distance = d;
	newprim->type = TYPE_PLANE;

	return newprim;
}

IDrawPrimitive* IDrawPrimitive::CreateScreenQuad(int width, int height, int offsetX, int offsetY, float scaleFactor, const math::Vector4 &color)
{
	IDrawPrimitive* newprim = NULL;

#ifdef CORE_DIRECTX
	// Create a plane as a directx instance
	newprim = new directx::DXDrawPrimitive();
	dynamic_cast<directx::DXDrawPrimitive*>(newprim)->createScreenQuad(width, height, offsetX, offsetY, scaleFactor, color);
#endif

	newprim->type = TYPE_SCREENQUAD;

	return newprim;
}

IDrawPrimitive* IDrawPrimitive::CreateQuad(int width, int height, const math::Vector4 &color)
{
	IDrawPrimitive* newprim = NULL;

#ifdef CORE_DIRECTX
	// Create a plane as a directx instance
	newprim = new directx::DXDrawPrimitive();
	dynamic_cast<directx::DXDrawPrimitive*>(newprim)->createQuad(width, height, color);
#endif

	newprim->type = TYPE_QUAD;

	return newprim;
}

void IDrawPrimitive::GenTriGrid(int numVertRows, int numVertCols, float dx, float dz, std::vector<math::Vector3>& verts, std::vector<DWORD>& indices)
{
	int numVertices = numVertRows*numVertCols;
	int numCellRows = numVertRows-1;
	int numCellCols = numVertCols-1;

	int numTris = numCellRows*numCellCols*2;

	float width = (float)numCellCols * dx;
	float depth = (float)numCellRows * dz;

	//===========================================
	// Build vertices.

	// We first build the grid geometry centered about the origin and on
	// the xz-plane, row-by-row and in a top-down fashion.
	verts.resize( numVertices );

	// Offsets to translate grid from quadrant 4 to center of 
	// coordinate system.
	float xOffset = -width * 0.5f; 
	float zOffset =  depth * 0.5f;

	int k = 0;
	for(float i = 0; i < numVertRows; ++i)
	{
		for(float j = 0; j < numVertCols; ++j)
		{
			// Negate the depth coordinate to put in quadrant four.  
			// Then offset to center about coordinate system.
			verts[k].x =  j*dx + xOffset;
			verts[k].z = -i*dz + zOffset;
			verts[k].y =  0.0f;

			++k; // Next vertex
		}
	}

	//===========================================
	// Build indices.

	indices.resize(numTris * 3);
	 
	// Generate indices for each quad.
	k = 0;
	for(DWORD y = 0; y < (DWORD)numCellRows; ++y)
	{
		for(DWORD x = 0; x < (DWORD)numCellCols; ++x)
		{			
			indices[k]     =   y   * numVertCols + x;
			indices[k + 1] = (y+1) * numVertCols + x + 1;
			indices[k + 2] = (y+1) * numVertCols + x;
			
			indices[k + 3] =   y   * numVertCols + x;
			indices[k + 4] =   y   * numVertCols + x + 1;
			indices[k + 5] = (y+1) * numVertCols + x+1;
			
			// next quad
			k += 6;
		}
	}
}
